#include "stdafx.h"
#include "core/kernel.h"

namespace natrium {
	namespace core {
		Kernel::Kernel() {
			mChan.add<StopEvent>(this);
			mChan.add<Task::TaskCompleted>(this);

			mRunning = false;
		}

		Kernel::~Kernel() {
		}

		void Kernel::add(const TaskPtr& task) {
			if (task->getTaskFlags() & Task::BACKGROUND)
				mProcessor([this, task]() { execute(task); });				
			else {
				std::lock_guard<std::mutex> guard(mMutex);
				mTaskList.push_back(task);
			}
		}

		void Kernel::start() {
			mRunning = true;

			while (mRunning) {
				TaskList currentMain;
				{
					std::lock_guard<std::mutex> guard(mMutex);
					currentMain = std::move(mTaskList);
					mTaskList.clear(); //the move operation should have cleared the tasklist, but clear it anyway just to be sure
				}

				for (const auto& task: currentMain)
					execute(task);
			}
		}

		void Kernel::stop() {
			mRunning = false;
		}

		void Kernel::execute(const TaskPtr& t) {
			mChan.broadcast(Task::TaskBeginning(t));
			t->run();
			mChan.broadcast(Task::TaskCompleted(t));
		}

		void Kernel::operator()(const Kernel::StopEvent& ) {
			stop();
		}

		void Kernel::operator()(const Task::TaskCompleted& tc) {
			if (mRunning && (tc.mTask->getTaskFlags() & Task::REPEATING))
				add(tc.mTask);
		}
	}
}